﻿// BmpImage.cpp: implementation of the BmpImage class.
//
//////////////////////////////////////////////////////////////////////

#include "BmpImage.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
/**********************************************************
函数名：Display
功能：简单的显示图像
入口参数：pDC
出口参数：无
说明：仅用于图像的简单快速显示
**********************************************************/
BmpImage::BmpImage()
{

}


/**********************************************************
函数名：Display
功能：简单的显示图像
入口参数：pDC
出口参数：无
说明：仅用于图像的简单快速显示
**********************************************************/
BmpImage::BmpImage(CFile *BmpFile)
{
	this->BmpFile=BmpFile;
	LoadFile();
}


/**********************************************************
函数名：Display
功能：简单的显示图像
入口参数：pDC
出口参数：无
说明：仅用于图像的简单快速显示
**********************************************************/
BmpImage::~BmpImage()
{
	free(m_pData);
}


/**********************************************************
函数名：Display
功能：简单的显示图像
入口参数：pDC
出口参数：无
说明：仅用于图像的简单快速显示
**********************************************************/
BmpImage::BmpImage(CString filename)
{
	m_FileName=filename;
	BmpFile=new CFile(m_FileName, CFile::modeRead);
	LoadFile();
}


/**********************************************************
函数名：Display
功能：简单的显示图像
入口参数：pDC
出口参数：无
说明：仅用于图像的简单快速显示
**********************************************************/
BmpImage::BmpImage(const char *FileName)
{
	m_FileName=FileName;
	BmpFile=new CFile(m_FileName, CFile::modeRead);
	LoadFile();
}


/**********************************************************
函数名：Display
功能：简单的显示图像
入口参数：pDC
出口参数：无
说明：仅用于图像的简单快速显示
**********************************************************/
void BmpImage::Display(CDC *pDC)
{
	CBitmap m_bitmap;
	HBITMAP hBitmap=(HBITMAP)LoadImage(NULL,_T(m_FileName),IMAGE_BITMAP,
		0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);
	if(!hBitmap)return;
    m_bitmap.Attach (hBitmap);
	CDC dcImage;
	if(!dcImage.CreateCompatibleDC(pDC))
		return;
	BITMAP bm;
	m_bitmap.GetBitmap (&bm);
    dcImage.SelectObject (&m_bitmap);
	pDC->BitBlt (0,0,bm.bmWidth ,bm.bmHeight ,&dcImage,0,0,SRCCOPY);
}


/**********************************************************
函数名：Display
功能：显示图像
入口参数：hdc:设备句柄
出口参数：无
说明：与上不同，它主要用于对处理后的图像的数据的显示
**********************************************************/
void BmpImage::Display( HDC hdc)
{

	StretchDIBits(hdc,0,0,GetWidth(),GetHeight(),0,0,GetWidth(),
		GetHeight(),m_pData,m_pBmpInfo,NULL,MERGECOPY);
}

/**********************************************************
函数名：LoadFile
功能：获取图像的各种数据结构和数据
入口参数：无
出口参数：无
说明：该函数必须在所有其它成员函数之前被调用,否则将出现不可
       预料的结果,此函数并不进行图像的显示
**********************************************************/
int BmpImage::LoadFile()
{
	this->BmpFile->Close();
    //获取图像文件类型
	m_iImageType = FileType((const char *)m_FileName);
   	if( m_iImageType == 0 )
	{
		m_iLastError = IMAGELIB_UNSUPPORTED_FILETYPE;
		return( FALSE );
	}
	//m_iImageType=1;
	//图像句柄
	HGLOBAL m_hDib;
	//根据文件类型调用ImageLoad.dll动态链接库中的相应函数打开图像文件
	switch( m_iImageType )
	{
	case IMAGETYPE_BMP:
		m_hDib = LoadBMP(m_FileName);
		if( m_hDib == NULL )
		{
			m_iLastError = GetLastPicLibError();
			return( FALSE );
		}
		break;
	case IMAGETYPE_GIF:
		m_hDib = LoadGIF( m_FileName);
		if( m_hDib == NULL )
		{
			m_iLastError = GetLastPicLibError();
			return( FALSE );
		}
		break;
	case IMAGETYPE_JPG:
		m_hDib = LoadJPG( m_FileName);
		if( m_hDib == NULL )
		{
			m_iLastError = GetLastPicLibError();
			return( FALSE );
		}
		break;
	case IMAGETYPE_PCX:
		m_hDib = LoadPCX( m_FileName );
		if( m_hDib == NULL )
		{
			m_iLastError = GetLastPicLibError();
			return( FALSE );
		}
		break;
	case IMAGETYPE_TGA:
		m_hDib = LoadTGA( m_FileName );
		if( m_hDib == NULL )
		{
			m_iLastError = GetLastPicLibError();
			return( FALSE );
		}
		break;
	case IMAGETYPE_TIF:
		m_hDib = LoadTIF( m_FileName );
		if( m_hDib == NULL )
		{
			m_iLastError = GetLastPicLibError();
			return( FALSE );
		}
		break;
	}

	LPVOID lpTemp=GlobalLock(m_hDib);

	BYTE* pBmpBuf;
	pBmpBuf=(BYTE*)lpTemp;
	pBmpBuf+=sizeof(BITMAPFILEHEADER);
	//获取文件信息指针
    m_pBmpInfo = (BITMAPINFO*) pBmpBuf;
	//获取文件信息头指针
    m_pBmpInfoHeader = (BITMAPINFOHEADER*) pBmpBuf;
	//获取调色板指针
    m_pRGBTAB = (RGBQUAD*)(pBmpBuf + m_pBmpInfoHeader->biSize);
    int m_NumOfColorTab = GetNumOfColorTab();
    if (m_pBmpInfoHeader->biClrUsed == 0)
        m_pBmpInfoHeader->biClrUsed =m_NumOfColorTab;
	//获取彩色表的尺寸
    DWORD ColorTableSize = m_NumOfColorTab *sizeof(RGBQUAD);
    m_pData = pBmpBuf + m_pBmpInfoHeader->biSize
        + ColorTableSize;
	if (m_pRGBTAB == (RGBQUAD*)m_pData) // No color table
		m_pRGBTAB = NULL;
    m_pBmpInfoHeader->biSizeImage = GetSize();
	m_Valid = TRUE;

	::GlobalUnlock(lpTemp);

	//下面这部份不能删，因为linux下面并没有前面提到的图像读写库
    /*BmpFile->Read((void*)&m_BmpFileHeader,sizeof(BITMAPFILEHEADER));

    if (m_BmpFileHeader.bfType == 0x4d42)
    {
        DWORD fileLength = BmpFile->GetLength();
        DWORD size = fileLength - sizeof(BITMAPFILEHEADER);
        BYTE* pBmpBuf =(BYTE*)malloc(size);
		if(!pBmpBuf)
			return 1;
        BmpFile->Read((void*)pBmpBuf, size);
        //BmpFile->Close();
		//获取文件信息指针
        m_pBmpInfo = (BITMAPINFO*) pBmpBuf;
		//获取文件信息头指针
        m_pBmpInfoHeader = (BITMAPINFOHEADER*) pBmpBuf;
		//获取调色板指针
        m_pRGBTAB = (RGBQUAD*)(pBmpBuf + m_pBmpInfoHeader->biSize);
        int m_NumOfColorTab = GetNumOfColorTab();
        if (m_pBmpInfoHeader->biClrUsed == 0)
            m_pBmpInfoHeader->biClrUsed =m_NumOfColorTab;
		//获取彩色表的尺寸
        DWORD ColorTableSize = m_NumOfColorTab *sizeof(RGBQUAD);
        m_pData = pBmpBuf + m_pBmpInfoHeader->biSize
            + ColorTableSize;
		if (m_pRGBTAB == (RGBQUAD*)m_pData) // No color table
			m_pRGBTAB = NULL;
        m_pBmpInfoHeader->biSizeImage = GetSize();
		m_Valid = TRUE;
    }
    else
    {
        m_Valid = FALSE;
        AfxMessageBox("This isn't a bitmap file!");
    }*/

	return 0;
}

/**********************************************************
函数名：GetNumOfColorTab
功能：获取图像的调色板数目
入口参数：无
出口参数：调色板项数
说明：调色板的每项用四个字节表示，第四字节保留，前三字节分别为
	  黄绿蓝三颜色的值，一般而言16/24位图像无调色板
**********************************************************/
int BmpImage::GetNumOfColorTab()
{

    if ((m_pBmpInfoHeader->biClrUsed == 0)&&(m_pBmpInfoHeader->biBitCount<9))
	{
		switch (m_pBmpInfoHeader->biBitCount)
		{
		case 1: m_NumOfColorTab = 2; break;
		case 4: m_NumOfColorTab = 16; break;
		case 8: m_NumOfColorTab = 256;break;
		}
	}
    else
		m_NumOfColorTab = (DWORD) m_pBmpInfoHeader->biClrUsed;

    return m_NumOfColorTab;
}

/**********************************************************
函数名：GetSize
功能：获取图像的面积
入口参数：无
出口参数：图像面积
说明：图像的面积为其高*宽，单位为/像数点
**********************************************************/
int BmpImage::GetSize()
{
    if (m_pBmpInfoHeader->biSizeImage != 0)
        return m_pBmpInfoHeader->biSizeImage;
	else
    {
        DWORD height = (DWORD) GetHeight();
        DWORD width = (DWORD) GetWidth();
        return height * width;
    }
}

/**********************************************************
函数名：GetWidth
功能：获取图像宽度
入口参数：无
出口参数：图像宽度
说明：图像宽度的单位为/像数点
**********************************************************/
int BmpImage::GetWidth()
{
    return m_pBmpInfoHeader->biWidth;
}

/**********************************************************
函数名：GetHeight
功能：获取图像高度
入口参数：无
出口参数：图像高度
说明：图像高度的单位为/像数点
**********************************************************/
int BmpImage::GetHeight()
{
    return (UINT) m_pBmpInfoHeader->biHeight;
}

/**********************************************************
函数名：GetData
功能：获取图像的数据指针
入口参数：无
出口参数：m_pData:图像在内存中的数据的开始地址
说明：图像数据是指专门用于显示的数据，而非为组织其它数据服务的数据结构
**********************************************************/
BYTE* BmpImage::GetData()
{
    return m_pData;
}


/**********************************************************
函数名：GetBmpWidthBytes
功能：获取图像每一行占用的字节数
入口参数：无
出口参数：图像每一行占用的字节数
说明：图像每行占用的字节数必须为4的整数倍
**********************************************************/
int BmpImage::GetBmpWidthBytes()
{

	//DWORD dwWidth=m_pBitmapInfoHeader->biWidth;
	//DWORD dwWidthBytes;
	/*switch(m_pBmpInfoHeader->biBitCount)
	{
	case 1: dwWidthBytes = (nWidth + 7) / 8;
	case 4: dwWidthBytes = (nWidth + 1) / 2;
	case 8: dwWidthBytes = (nWidth + 1) / 2;
	case:(byBitCount == 24) dwWidthBytes = 3 * nWidth ;

	}
	while((dwWidthBytes & 3) != 0)dwWidthBytes++;*/


	return ((m_pBmpInfoHeader->biBitCount*
		m_pBmpInfoHeader->biWidth+31)>>5)<<2;
}


/**********************************************************
函数名：GetBmpInfo
功能：获取位图信息头指针
入口参数：无
出口参数：位图信息头指针
说明：位图信息头用于描述位图文件的大小，压缩方式，图像宽和高度等
**********************************************************/
BITMAPINFO* BmpImage::GetBmpInfo()
{
	return m_pBmpInfo;
}


/**********************************************************
函数名：GetBitsPerPix
功能：获取位图图像的颜色位数
入口参数：无
出口参数：m_NumOfColors:位图信息头指针
说明：位图图像的颜色位数是指表示每个像素点所用的二进制位数
**********************************************************/
int BmpImage::GetBitsPerPix()
{
	 if ((m_pBmpInfoHeader->biClrUsed == 0)&&(m_pBmpInfoHeader->biBitCount<9))
	{
		switch (m_pBmpInfoHeader->biBitCount)
		{
		case 1: m_NumOfColors = 2; break;
		case 4: m_NumOfColors = 16; break;
		case 8: m_NumOfColors = 256;break;
		case 16: m_NumOfColors =0xffff;break;
		case 24: m_NumOfColors = 0xffffff;break;
		}
	}
    else
		m_NumOfColors = (DWORD) m_pBmpInfoHeader->biClrUsed;

    return m_NumOfColors;
}


/**********************************************************
函数名：GetBytesPerPix
功能：获取位图表示每个像素点所用的字节数
入口参数：无
出口参数：字节数
说明：不同位数的彩色图像表示像素点所用的字节数不同，16位色
	   用两个字节，24位色用三个字节,8位色用一个字节等
**********************************************************/
int BmpImage::GetBytesPerPix()
{
	return m_pBmpInfoHeader->biBitCount/8;
}

RGBQUAD* BmpImage::GetRGBTab()
{
	return m_pRGBTAB;
}

void BmpImage::SetHeight(int height)
{
	m_pBmpInfoHeader->biHeight=height;
}

void BmpImage::SetBmpData(BYTE *data)
{

	this->m_pData=data;
}

void BmpImage::SetWidth(int width)
{
	m_pBmpInfoHeader->biWidth=width;
}

void BmpImage::SetImageSize()
{
	m_pBmpInfoHeader->biSizeImage=(GetBytesPerPix()*GetWidth()*GetHeight());
}

bool BmpImage::SaveFile(const char *cFileName)
{
	return true;
}
